﻿using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.CSharp.Syntax;
using System.Text;
using System.IO;
using ICSharpCode.Decompiler.Metadata;

namespace DllCallMeshAnalysisILSpy
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");

            var filePath = "D:\\CompanyProjects\\tita-dotnet-project\\Public\\Beisen.Tita.WebAPI.Controller\\bin\\Debug\\";
            var fileName = "Beisen.Tita.WebAPI.Controller.dll";
            var fileFullName = Path.Combine(filePath, fileName);

            var assemblyResolver = new UniversalAssemblyResolver(fileFullName, true, null);
            assemblyResolver.AddSearchDirectory(filePath);

            var decompiler = new CSharpDecompiler(fileFullName, assemblyResolver, new DecompilerSettings());

            var deepCall = new DeepCallAstVisitor();
            deepCall.OnTypeVisit = (t) =>
            {
                decompiler.DecompileType(new FullTypeName(t.FullName));
            };

            var tree = decompiler.DecompileType(new FullTypeName("Beisen.Tita.WebAPI.Controller.Controllers.DepartmentV2ApiController"));

            tree.AcceptVisitor(deepCall);

            var text = BuildTreeStr(tree);

            //Console.WriteLine(text);
            File.WriteAllText("D:\\a2.cs", text);

            Console.ReadLine();
        }


        static string BuildTreeStr(AstNode _node)
        {
            var sb = new StringBuilder();

            _Deep(_node);

            return sb.ToString();

            void _Deep(AstNode node, int deep = 0)
            {
                var header = BuildHead(deep);

                if (IsSingleLine(node))
                {
                    sb.AppendLine(header + $"{node}".Trim());
                    return;
                }

                if (IsBox(node))
                {
                    var childs = node.Children?.ToList();

                    if (childs?.Any() == true)
                    {
                        foreach (var child in childs)
                        {
                            _Deep(child, deep + 1);
                        }
                    }
                }
                else
                {
                    sb.AppendLine(header + $"({node.GetType().FullName}){node}".Trim());
                }
            }

            string BuildHead(int deep)
            {
                var s = new StringBuilder();

                for (int i = 0; i < deep; i++)
                {
                    s.Append("\t");
                }

                return s.ToString();
            }

            bool IsSingleLine(AstNode node)
            {
                var nodeType = node.GetType();
                if (nodeType == typeof(UsingDeclaration))
                    return true;

                return false;
            }

            bool IsBox(AstNode node)
            {
                var nodeType = node.GetType();
                //if (nodeType == typeof(SyntaxTree))
                //    return true;

                //if (nodeType == typeof(BlockStatement))
                //    return true;


                return new[]
                {
                    typeof(SyntaxTree),
                    typeof(BlockStatement),
                    //typeof(NamespaceDeclaration),
                }.Contains(nodeType);
            }
        }
    }
}
